﻿
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace MyJWT
{
    public class Utils
    {

        public static string Sign(Header header, Payload payload, string privateKey)
        {
            // 按字典排序 再签名
            //var headerString = CreateSortString(header);
            //var payloadString = CreateSortString(payload);
            var headerString = JsonSerializer.Serialize(header);
            var payloadString = JsonSerializer.Serialize(payload);
            var base64headerString = Base64UrlEncode(headerString);
            var base64payloadString = Base64UrlEncode(payloadString);

            var allString = $"{base64headerString}.{base64payloadString}";
            var sign = MyJWT.RSAUtil.Sign(MyJWT.RSAKeyConverter.ToXmlPrivateKey(privateKey), allString);
            return $"{allString}.{sign}";
        }

        public static (bool isSuccess, Payload payload) SignCheck(string sign, string publicKey)
        {
            var tokens = sign.Split('.');
            if (tokens.Length < 3) throw new Exception("token错误");
            var header = JsonSerializer.Deserialize<Header>(Base64UrlDecode(tokens[0]));
            var payload = JsonSerializer.Deserialize<Payload>(Base64UrlDecode(tokens[1]));

            var headerString = JsonSerializer.Serialize(header);
            var payloadString = JsonSerializer.Serialize(payload);
            var base64headerString = Base64UrlEncode(headerString);
            var base64payloadString = Base64UrlEncode(payloadString);
            var allString = $"{base64headerString}.{base64payloadString}";
            return (RSAUtil.SignCheck(allString, RSAKeyConverter.ToXmlPublicKey(publicKey), tokens[2]), payload);
        }

        private static string Base64UrlEncode(string text)
        {
            var bytes = Encoding.UTF8.GetBytes(text);
            return Microsoft.AspNetCore.WebUtilities.Base64UrlTextEncoder.Encode(bytes);

        }

        private static string Base64UrlDecode(string text)
        {
            var bytes = Microsoft.AspNetCore.WebUtilities.Base64UrlTextEncoder.Decode(text);
            //var bytes = Convert.FromBase64String(text.Replace('-', '+').Replace('_', '/'));
            return Encoding.UTF8.GetString(bytes);
        }

        //private static string CreateSortString<T>(T t)
        //{
        //    var properties = t.GetType().GetProperties();
        //    var sortProperties = properties.OrderBy(x => x.Name).ToArray();
        //    var sb = new StringBuilder();
        //    for (int i = 0; i < sortProperties.Length; i++)
        //    {
        //        var value = sortProperties[i].GetValue(t, null) ?? string.Empty;
        //        sb.Append($"{sortProperties[i].Name}={value.ToString()}");
        //    }
        //    return sb.ToString();
        //}
    }
}
